package com.ld.security.server.admin.modules.ge.service.impl;

import com.ld.security.common.core.base.column.ListString;
import com.ld.security.common.core.exception.ApiException;
import com.ld.security.common.core.util.JsonUtil;
import com.ld.security.common.core.util.ReflectionUtil;
import com.ld.security.common.core.util.StringUtil;
import com.ld.security.common.core.util.TemplateUtil;
import com.ld.security.common.mybatis.base.po.IdsPo;
import com.ld.security.common.mybatis.base.po.PagePo;
import com.ld.security.common.mybatis.base.service.ISuperServiceImpl;
import com.ld.security.common.mybatis.base.vo.PageVo;
import com.ld.security.common.mybatis.util.JdbcUtil;
import com.ld.security.server.admin.modules.ge.constant.GeModelConstant;
import com.ld.security.server.admin.modules.ge.entity.*;
import com.ld.security.server.admin.modules.ge.mapping.IGeViewMapping;
import com.ld.security.server.admin.modules.ge.po.GeCodelPo;
import com.ld.security.server.admin.modules.ge.po.UseTableInitViewPo;
import com.ld.security.server.admin.modules.ge.po.ViewSavePo;
import com.ld.security.server.admin.modules.ge.service.*;
import com.ld.security.server.admin.modules.ge.util.GeScopeUtil;
import com.ld.security.server.admin.modules.ge.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Transactional
class GeViewServiceImpl extends ISuperServiceImpl<GeViewEntity> implements
        IGeViewService {

    @Autowired
    IGeModelService iGeModelService;

    @Autowired
    IGeTableService iGeTableService;

    @Autowired
    IGeViewTelService iGeViewTelService;

    @Autowired
    IGeViewMapping iGeViewMapping;

    @Autowired
    IGeFieldService iGeFieldService;

    @Autowired
    IGeFuncService iGeFuncService;

    @Autowired
    IGeEarlyModelService iGeEarlyModelService;


    @Override
    public RenderViewVo getRenderView(String id ) {

        RenderViewVo vo =new RenderViewVo();
        vo.setId(id);
        this.proxyQuery(vo);
        List<String> ids =   vo.getModels().stream().map(v -> v.getId()).collect(Collectors.toList());
        EarlyDetailsVo detailsVo = iGeEarlyModelService.getEarlyDetails(ids);

        vo.setEarlyModels(detailsVo.getEarlyModels());

        return vo;
    }


    @Override
    public int removeByIds(Collection<String> ids) {
    for (String id : ids) {
        RenderViewVo vo =  this.getRenderView(id);
        this.proxyRemove(vo);
    }
    return ids.size();

    }


    @Override
    public String generatingCode(String id) {

        RenderViewVo vo =  getRenderView(id);
        Map params = ReflectionUtil.clone(vo,Map.class);
        return TemplateUtil.renderString(vo.getViewTel().getTemplateCode(),params);

    }

    @Override
    public byte[] generatingCodeZip(IdsPo po) {
        HashMap map = new HashMap<>();

        for (String id : po.getIds()) {
            GeCodelPo pp =new GeCodelPo();
            pp.setId(id);

            RenderViewVo vo =  getRenderView(id);
            Map params = ReflectionUtil.clone(vo,Map.class);
            String code =  TemplateUtil.renderString(vo.getViewTel().getTemplateCode(),params);
            if(StringUtil.isNull(code)){
                ApiException.throw400("缺少模板代码");
            }
            String path = vo.getProject().getBasePath()+"."+
                    vo.getPack().getModuleName()+ "."+
                    vo.getViewTel().getPackageName()+"."+
                    vo.getViewTel().getNamePrefix()+
                   vo.getView().getFileName() +
                    vo.getViewTel().getNameSuffix();
            String key = path.replaceAll("\\.","/")+vo.getViewTel().getFileType();
            map.put(key,code);
        }

        return TemplateUtil.createTemplateZip(map);
    }




    @Override
    public void useTableInitView(UseTableInitViewPo po) {

        for (String tableId : po.getTableIds()) {
            TableDetailsVo vo =  iGeTableService.getTableDetails(tableId);


            for (String viewTelId : po.getViewTelIds()) {

                ViewTelSaveVo viewTelSaveVo =  iGeViewTelService.getViewTelSaveVo(viewTelId);

                GeViewTelEntity viewTel =  viewTelSaveVo.getViewTel();


                GeViewEntity geView =  this.newInstance();

                geView.setDataSourceId(vo.getTable().getDataSourceId());
                geView.setViewTelId(viewTel.getId());

                geView.setPackId(po.getPackId());
                geView.setLabel(vo.getTable().getLabel());
                geView.setProjectId(po.getProjectId());
                geView.setViewArgs(viewTel.getViewArgs());


                String fieldName = StringUtil.columnToJava(vo.getTable().getTableName());
                fieldName = StringUtil.toUpperCaseFirstOne(fieldName);

                geView.setFileName(fieldName);


                //试图保存
                this.save(geView);

                //根据模型模板定义
                for (GeModelTelEntity geModelTel : viewTelSaveVo.getModelTels()) {
                    GeModelEntity modelEntity = iGeModelService.newInstance();
                    modelEntity.setModelTelId(geModelTel.getId());
                    modelEntity.setViewId(geView.getId());
                    modelEntity.setDataSourceId(geView.getDataSourceId());
                    modelEntity.setCode(geModelTel.getCode());
                    modelEntity.setLabel(geModelTel.getLabel());
                    modelEntity.setModelType(GeModelConstant.modelType.model);

                    List<GeFieldEntity> fs = vo.columnToFields();

                    modelEntity.setTableIds(new ListString( fs.get(0).getTableName()));

                    iGeModelService.save(modelEntity);
                    for (GeFieldEntity f : fs) {
                        f.setModelId(modelEntity.getId());
                    }
                    iGeFieldService.saveBatch(fs);
                }

                List<GeFuncEntity> funcs =  viewTelSaveVo.getFuncTels().stream().map(v -> {
                    GeFuncEntity func =  JsonUtil.clone(v,GeFuncEntity.class);
                    func.setViewId(geView.getId());
                    func.setFuncTelId(v.getId());
                    return func;
                }).collect(Collectors.toList());

                iGeFuncService.saveBatch(funcs);

            }


        }

    }

    @Override
    public void saveView(ViewSavePo po) {
    for (GeCompEntity geCompEntity : po.getComps()) {
        if( StringUtil.isNotNull( geCompEntity.getProjectId())){
            geCompEntity.setProjectId(po.getView().getProjectId());
        }
    }
        this.proxyQuery(po);
        if(StringUtil.isNotNull(po.getView().getId())){
            this.deleteView(po.getView().getId());
        }
        int srotVal = 0;
        for (GeModelEntity geModelEntity : po.getModels()) {
            geModelEntity.setDataSourceId(po.getView().getDataSourceId());

            geModelEntity.setSortVal( srotVal ++ );
        }

        JdbcUtil.proxySave(po);
    }


    @Override
    public void deleteView(String id) {
        GeViewSaveVo vo = this.getGeViewSave(id);
        JdbcUtil.proxyRemove(vo);
    }

    @Override
    public GeViewSaveVo getGeViewSave(String id) {
        GeViewSaveVo vo = new GeViewSaveVo();
        vo.setId(id);
        JdbcUtil.proxyQuery(vo);
        return vo;
    }

    @Override
    public PageVo<GeViewEntity> dataPerPage(PagePo<GeViewEntity> po) {
        GeScopeUtil.queryBefore(po.getQuery());

        PageVo<GeViewEntity> pageVo =  JdbcUtil.page(po);

        GeScopeUtil.queryAfter(pageVo.getList());

        return pageVo;
    }

    @PostConstruct
    public void run(){

    }

    @Override
    public String generatingTemplateCode(String path, Map params) {
        return TemplateUtil.renderTemplate(path,params);
    }
}
